import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Client {
	private static Scanner scanner = new Scanner(System.in);
	public static Request request = new Request();

	public static void main(String[] args) {

		System.out.println("\n\nWelcome to Security Trading System!!");
		System.out.println("Pre-Populated Data: ");
		populatePortfolios();
		populateStocks();

		for (int i = 0; true; i++) {
			System.out.println("\n\nWelcome to Security Trading System!!");
			System.out.println("Please Select:");
			System.out.println("1. Portfolio");
			System.out.println("2. Report");
			System.out.println("3. Clock");
			System.out.println("4. If you want to Exit");

			int choice = scanner.nextInt();

			System.out.println("You entered " + choice);

			switch (choice) {
			case 1:
				portfolioOperations();
				break;
			case 2:
				reportOperations();
				break;
			case 3:
				startStopTimer();
				break;
			case 4:
				System.exit(0);
			}
		}
	}

	private static void startStopTimer() {
		int profileChoice;
		while (true) {
			System.out.println("\n1. Start Market");
			System.out.println("2. Stop Market");
			System.out.println("3. Forward Date");

			profileChoice = scanner.nextInt();
			if (profileChoice == 1) {
				Timer t = new Timer();
				t.StartStopMSV(true);
				break;
			} else if (profileChoice == 2) {
				Timer t = new Timer();
				t.StartStopMSV(false);
				break;
			} else if (profileChoice == 3) {
				System.out.println("Enter days: ");
				int timestamp = scanner.nextInt();
				Timer t = new Timer();
				t.setDate(timestamp);
				break;

			} else {
				System.out.println("Please enter options either 1 or 2");
				continue;
			}
		}
	}

	private static void populateStocks() {
		System.out.println("\nListing Stocks: ");
		Stock stock = null;
		for (int i = 0; i < 3; i++) {
			Request.stockId++;
			stock = new Stock();
			stock.addSecurity(Request.stockId, (i + 1) * 100);
		}
		stock.listSecurity();
	}

	private static void populatePortfolios() {
		System.out.println("\nCreating 1 Company Portfolio..");
		Request.portfolioId++;
		Portfolio portfolio = new Portfolio(Request.portfolioId,
				portType.COMPANY, acctype.CASH);

		PortfolioRepository.getPortfolioRepository().addPortfolio(portfolio);
		Account account = new Account();
		Request.accountId++;
		account.createAccount(Request.accountId, acctype.CASH,
				Request.portfolioId);
		portfolio.getAccounts().add(account);
		portfolio.display();

		System.out.println("\nCreating 2 Individual Portfolios..");
		for (int i = 0; i < 2; i++) {
			System.out.println("\nIndividual : " + (i + 1));
			Request.portfolioId++;
			portfolio = new Portfolio(Request.portfolioId, portType.INDIVIDUAL,
					acctype.CASH);

			PortfolioRepository.getPortfolioRepository()
					.addPortfolio(portfolio);
			account = new Account();
			Request.accountId++;
			account.createAccount(Request.accountId, acctype.CASH,
					Request.portfolioId);
			portfolio.getAccounts().add(account);
			portfolio.display();
		}
	}

	private static void reportOperations() {
		System.out.println("Select report: ");
		System.out.println("1. List all securities");
		System.out.println("2. List all orders");
		int report = scanner.nextInt();
		System.out.println("Select format: ");
		System.out.println("1. Online Format: ");
		System.out.println("2. Email Format: ");
		int formatchoice = scanner.nextInt();
		switch (report) {
		case 1:
			request.listSecurity(formatchoice);
			break;

		case 2:
			request.listOrders(formatchoice);
			break;
		}

	}

	private static void portfolioOperations() {
		int profileChoice;
		while (true) {
			System.out.println("\n1. Company");
			System.out.println("2. Individual");

			profileChoice = scanner.nextInt();
			if (profileChoice == 1) {
				request.setPortfolioType(portType.COMPANY);
				break;
			} else if (profileChoice == 2) {
				request.setPortfolioType(portType.INDIVIDUAL);
				break;
			} else {
				System.out.println("Please enter options either 1 or 2");
				continue;
			}
		}

		System.out.println("\n1. Create Portfolio");
		System.out.println("2. Manage Account");
		System.out.println("3. Manage Orders");
		int operationChoice = scanner.nextInt();
		switch (operationChoice) {
		case 1: {
			request.setRequestId(Constants.CREATE_PORTFOLIO);
			request.processRequest();
			break;
		}
		case 2: {
			System.out.println("Enter Portfolio Id: ");
			int portfolioId = scanner.nextInt();
			Portfolio portfolio = PortfolioRepository.getPortfolioRepository()
					.getPortfolioWithID(portfolioId);

			if (portfolio == null) {
				System.out.println("Portfolio Does not exists");
			} else if ((profileChoice == 1
					&& portType.COMPANY.equals(portfolio.getPortfolioType()) || (profileChoice == 2 && portType.INDIVIDUAL
					.equals(portfolio.getPortfolioType())))) {
				System.out.println("\n1. Add Account");
				System.out.println("2. View Accounts");
				System.out.println("3. Update Account");
				System.out.println("4. Delete Account");
				int accountRequest = scanner.nextInt();

				if (accountRequest == 3 || accountRequest == 4) {

					while (true) {
						System.out.println("\nEnter Account Id: ");
						int accountId = scanner.nextInt();
						if (PortfolioRepository.getPortfolioRepository()
								.getAccount(accountId) != null) {
							request.setRequestAccountId(accountId);
							System.out.println("\nEnter Balance: ");
							int accountBalance = scanner.nextInt();
							request.setAccountBalance(accountBalance);
							break;
						} else {
							System.out.println("Account does not exists!");
							continue;
						}
					}
				}
				request.setRequestPortfolioId(portfolioId);
				request.setAccountRequest(accountRequest);
				request.setRequestId(Constants.MANAGE_ACCOUNTS);
				request.processRequest();
			} else {
				System.out.println("Portfolio does not exists!");
			}
			break;
		}

		case 3: {
			System.out.println("Enter Portfolio Id: ");
			int portfolioId = scanner.nextInt();
			Portfolio portfolio = PortfolioRepository.getPortfolioRepository()
					.getPortfolioWithID(portfolioId);
			if (portfolio == null) {
				System.out.println("Portfolio Does not exists");
			} else if ((profileChoice == 1 && portType.COMPANY.equals(portfolio
					.getPortfolioType()))) {

				System.out.println("\n1. Create New Stocks");
				System.out.println("2. List Stocks ");
				System.out.println("3. Create Mutual Funds");
				int orderRequest = scanner.nextInt();
				switch (orderRequest) {
				case 1: {
					System.out.println("\nEnter Stock Price: ");
					double stockPrice = scanner.nextDouble();
					request.setStockPrice(stockPrice);
					request.setRequestPortfolioId(portfolioId);
					request.setOrderRequest(orderRequest);
					request.setRequestId(Constants.MANAGE_ORDERS);
					request.processRequest();
					break;
				}

				case 2: {
					request.setRequestPortfolioId(portfolioId);
					request.setOrderRequest(orderRequest);
					request.setRequestId(Constants.MANAGE_ORDERS);
					request.processRequest();
					break;
				}

				case 3: {
					Stock stock = new Stock();
					stock.listSecurity();
					System.out.println("\nEnter Total number of Stocks: ");
					int numberOfStocks = scanner.nextInt();
					Map<Integer, Integer> stockDetailsInMf = new HashMap<Integer, Integer>();
					int stockId, quantity;
					for (int i = 0; i < numberOfStocks; i++) {
						System.out.println("Enter Stock Id: ");
						stockId = scanner.nextInt();
						System.out.println("Enter Quantity for Stock Id "
								+ stockId + " : ");
						quantity = scanner.nextInt();
						stockDetailsInMf.put(stockId, quantity);
					}
					System.out.println("\nEnter total units of Mutual Fund: ");
					int mutualFundUnits = scanner.nextInt();
					request.setMutualFundUnits(mutualFundUnits);
					request.setStockDetailsInMf(stockDetailsInMf);
					request.setRequestPortfolioId(portfolioId);
					request.setOrderRequest(orderRequest);
					request.setRequestId(Constants.MANAGE_ORDERS);
					request.processRequest();
					break;
				}
				}
			} else if (profileChoice == 2
					&& portType.INDIVIDUAL.equals(portfolio.getPortfolioType())) {

				System.out.println("\n1. Create Order");
				System.out.println("2. View Orders");
				System.out.println("3. Update Order");
				System.out.println("4. Delete Order");
				int orderRequest = scanner.nextInt();

				System.out.println("Enter Account Id: ");
				int accountId = scanner.nextInt();
				for (Account account : portfolio.getAccounts()) {
					if (account.getAccountId() == accountId) {

						if (orderRequest == 1) {
							System.out.println("\nEnter Order Type: ");
							System.out.println("1. Stock Order");
							System.out.println("2. Mutual Order");
							int securityTypeInput = scanner.nextInt();

							while (true) {
								if (securityTypeInput == 1) {
									request.setSecurityType(SecurityType.STOCKS);
								} else if (securityTypeInput == 2) {

									request.setSecurityType(SecurityType.MUTUAL_FUNDS);
								} else {
									System.out
											.println("Invalid input! Please enter Stock Order or Mutual Fund Order.");
									continue;
								}
								while (true) {
									System.out
											.println("\nEnter order Category: ");
									System.out.println("1. BUY");
									System.out.println("2. SELL");
									int orderCategory = scanner.nextInt();

									if (securityTypeInput == 1) {
										if (orderCategory == 1) {
											System.out
													.println("\nEnter Stock Id: ");
											int stockId = scanner.nextInt();
											request.setRequestStockId(stockId);

											System.out
													.println("\nEnter Quantity: ");
											int quantity = scanner.nextInt();
											request.setRequestStockQuantity(quantity);

											request.setOrderCategory(OrderCategory.BUY);
										} else if (orderCategory == 2) {
											System.out
													.println("Existing Stocks: ");
											for (Stock stock : account
													.getStocks()) {
												System.out.println("Stock Id: "
														+ stock.getStockId());
												System.out
														.println("Stock Name: "
																+ stock.getStockName());
												System.out
														.println("Stock Description: "
																+ stock.getStockDesc());
												System.out
														.println("Stock Price: "
																+ stock.getStockPrice());
											}

											System.out
													.println("\nEnter Stock Id: ");
											int stockId = scanner.nextInt();
											request.setRequestStockId(stockId);

											System.out
													.println("\nEnter Quantity: ");
											int quantity = scanner.nextInt();
											request.setRequestStockQuantity(quantity);
											request.setOrderCategory(OrderCategory.SELL);
										} else {
											System.out
													.println("Invalid input! Please enter: BUY or SELL.");
											continue;
										}
										if (securityTypeInput == Constants.STOCKS) {
											System.out
													.println("\nEnter Order Type: ");
											System.out.println("1. Limit");
											System.out.println("2. Market");
											int orderTypeId = scanner.nextInt();
											if (orderTypeId == 1) {
												request.setOrderType(OrderType.LIMIT);
												System.out
														.println("\nEnter Price Limit : ");
												double priceLimit = scanner
														.nextDouble();
												request.setPriceLimit(priceLimit);

												System.out
														.println("\nEnter Time Limit (in Days): ");
												int timestamp = scanner
														.nextInt();
												request.setTimeStamp(timestamp);

											} else if (orderTypeId == 2) {
												request.setOrderType(OrderType.MARKET);
											} else {
												System.out
														.println("Invalid input! Please enter: Limit or Market.");
												continue;
											}
										}
									} else {

										if (orderCategory == 1) {
											System.out
													.println("\n Listing all Mutual Funds");
											MutualFund mutualFund = new MutualFund();
											mutualFund.listSecurity();
											System.out
													.println("\nEnter Mutual Fund Id: ");
											int mutualFundId = scanner
													.nextInt();
											if (MutualFundRepository
													.getMutualFundRepository()
													.getMutualFund(mutualFundId) != null) {
												request.setRequestMutualFundId(mutualFundId);

												System.out
														.println("\nEnter Quantity: ");
												int quantity = scanner
														.nextInt();
												request.setRequestMFQuantity(quantity);

												request.setOrderCategory(OrderCategory.BUY);
											} else {
												System.out
														.println("Mutual Fund does not exists!");
												continue;
											}
										} else if (orderCategory == 2) {
											System.out
													.println("Existing Mutual Funds: ");
											for (MutualFund mutualFund : account
													.getMutualFunds()) {
												System.out
														.println("Mutual Fund Id: "
																+ mutualFund
																		.getMutualFundId());
												System.out
														.println("Mutual Fund Name: "
																+ mutualFund
																		.getMutualFundName());
												System.out
														.println("Mutual Fund Description: "
																+ mutualFund
																		.getMutualFundDesc());
												System.out
														.println("Mutual Fund Price: "
																+ mutualFund
																		.getMutualFundPrice());
											}
											System.out
													.println("\nEnter Mutual Fund Id: ");
											int mutualFundId = scanner
													.nextInt();

											if (MutualFundRepository
													.getMutualFundRepository()
													.getMutualFund(mutualFundId) != null) {
												request.setRequestMutualFundId(mutualFundId);

												System.out
														.println("\nEnter Quantity: ");
												int quantity = scanner
														.nextInt();
												request.setRequestMFQuantity(quantity);
												request.setOrderCategory(OrderCategory.SELL);
											} else {
												System.out
														.println("Mutual Fund does not exists!");
												continue;
											}
										} else {
											System.out
													.println("Invalid input! Please enter: BUY or SELL.");
											continue;
										}
									}
									break;
								}

								request.setRequestPortfolioId(portfolioId);
								request.setRequestAccountId(accountId);
								request.setOrderRequest(orderRequest);
								request.setRequestId(Constants.MANAGE_ORDERS);
								request.processRequest();
								break;
							}
						} else if (orderRequest == 2) {

							request.setRequestPortfolioId(portfolioId);
							request.setRequestAccountId(accountId);
							request.setOrderRequest(orderRequest);
							request.setRequestId(Constants.MANAGE_ORDERS);
							request.processRequest();
							break;
						} else if (orderRequest == 3 || orderRequest == 4) {
							System.out.println("Enter Order Id: ");
							int requestOrderId = scanner.nextInt();
							request.setRequestOrderId(requestOrderId);
							AbstractOrder order = OrderRepository
									.getOrderRepository().getOrder(
											requestOrderId);

							if (order != null) {
								if (orderRequest == 3) {
									if ((OrderType.LIMIT).equals(order
											.getOrderType())) {
										System.out.println("Enter new Price: ");
										double requestNewPrice = scanner
												.nextInt();
										request.setRequestNewPriceLimit(requestNewPrice);
										System.out
												.println("Enter new Quantity: ");
										int requestNewQuantity = scanner
												.nextInt();
										request.setRequestNewQuantity(requestNewQuantity);
									} else {
										System.out
												.println("Market Orders cannot be updated! ");
									}

								}
							} else {
								System.out.println("Order does not exists!");
							}
							request.setRequestPortfolioId(portfolioId);
							request.setRequestAccountId(accountId);
							request.setOrderRequest(orderRequest);
							request.setRequestId(Constants.MANAGE_ORDERS);
							request.processRequest();
							break;
						}
						break;
					} else {
						System.out.println("Account does not exists! ");
					}
				}
			} else {
				System.out.println("Portfolio does not exists!");
				break;
			}
		}
		}
	}
}
